var vverbose = true;
var vvverbose = true;
var isWin = framework.runtime.osName.toLowerCase().match("windows");
var isLinux = framework.runtime.osName.toLowerCase().match("linux");
var isMac = !isWin && !isLinux;

var log;
try {
	log = gadget.debug.error;
} catch (e) {
	log = function (a) {};

}
//log = function(x) { if(x.length == 0) return; alert(x)}
function __FUNCTION() {
//	return "";
	try {
		throw Exception("");
	} catch (e) {
		var line = e.stack.split("\n")[1];
		return line.substring(0, line.indexOf("@")).replace(/\[object\ ([^\]]*)\]/g, "$1").replace(/{[^}].*/, "");
	}
}
if(!Array.prototype.push){
	Array.prototype.push=function(x){
		this[this.length]=x;
		return true
	}
};

if (!Array.prototype.pop){
	Array.prototype.pop=function(){
		var response = this[this.length-1];
		this.length--;
		return response
	}
};

Object.prototype.forEach = function (fun) {
	var len = this.length >>> 0;
	if (typeof fun != "function") {
		throw new TypeError;
	}
	for (var i = 0; i < len; i++) {
		if (i in this) {
			fun(this[i], i, this);
		}
	}
};

Array.prototype.forEach = Object.prototype.forEach;
Object.prototype.grep = function (ident, reverse) {
	// TODO: make simple '===' if (typeof ident == typeof this[i]) - test with tv3 tv3+
	var ret = [];
	var escapeChars = ["+", "-", "/", " ", "[", "]", "("];
	if (typeof ident == "string" || ident instanceof RegExp) {
		if (typeof ident == "string") {
			var exp = "";
			for (var i = 0; i < ident.length; i++) {
				for (var j = 0; j < escapeChars.length; j++) {
					if (escapeChars[j] == ident.charAt(i) && i != 0 && ident.charAt(i - 1) != "\\") {
						exp += "\\";
					}
				}
				exp += ident.charAt(i);
			}
			exp = RegExp(exp);
		} else {
			var exp = ident;
		}
		if (typeof reverse == "undefined" || reverse == false) {
			this.forEach(function (iter, index, arr) {
				exp.test(iter) && ret.push(typeof iter == "string" ? iter : iter.toString());
			});
		} else {
			this.forEach(function (iter, index, arr) {
				!exp.test(iter) && ret.push(typeof iter == "string" ? iter : iter.toString());
			});
		}
	} else if (typeof ident == "boolean") {
		if (typeof reverse == "undefined" || reverse == false) {
			this.forEach(function (iter, index, arr) {
				iter === ident && ret.push(iter);
			});
		} else {
			this.forEach(function (iter, index, arr) {
				iter !== ident && ret.push(iter);
			});
		}
	} else {
		if (typeof reverse == "undefined" || reverse == false) {
			this.forEach(function (iter, index, arr) {
				iter == ident && ret.push(typeof ident == "number" ? parseInt(iter) : iter);
			});
		} else {
			this.forEach(function (iter, index, arr) {
				iter != ident && ret.push(typeof ident == "number" ? parseInt(iter) : iter);
			});
		}
	}
	return ret;
};

Array.prototype.grep = Object.prototype.grep;
String.prototype.trim = function () {
	return this.replace(/^\s+|\s+$/g, "");
};
function _nop() {
	var nop = 255;
	nop++;
	nop = null;
}

function loadImageStream(url, cb) {
	if (vverbose) {
		log(__FUNCTION());
	}
	xhrGet({
		url:url,
		onSuccess:cb,
		onError:function (status, xhrIo) {
			gadget.debug.error("Async loading of image stream failed ( " + url + " )");
		},
		handleAs:"img"
	});
}

function loadResponse(http, handleAs) {
	if (vverbose) {
		log(__FUNCTION());
	}
	if (handleAs == "xml" && typeof http.responseXml != "undefined") {
		return http.responseXml;
	} else if (handleAs == "xml") {
		var doc = new DOMDocument;
		doc.loadXml(http.responseText);
		if (doc.parseError.errorCode != 0)
			debug.error("SimpleXmlParser ERROR: " + doc.parseError.reason);
		return doc;
	} else if (handleAs == "img") {
		return http.responseStream || null;
	} else {
		return http.responseText;
	}
}

function xhrGet(params) {
	try {
		var async = def(params.onSuccess) && typeof params.onSuccess == "function";
		var mime = def(params.handleAs) ? params.handleAs : "text";
		var http = new XMLHttpRequest;
		http.open("get", params.url, async);
		http.onreadystatechange = function () {
			if (http.readyState == 4) {
				if (http.status == 200) {
					if (async) {
						params.onSuccess(loadResponse(http, mime), http);
					} else if (async && def(params.onError)) {
						params.onError(http.status, http);
					}
				}
			}
		};

		http.send(null);
		if (!async) {
			return loadResponse(http, params.handleAs);
		}
	} catch (e) {
		log("@xhrGet: " + e.message);
	}
}

function getFeed(cb, d, h) {
	if (vverbose) {
		log(__FUNCTION());
	}
	try {
		g_Feed = null;
		xml_ajaxIcon.visible = true;
		if (d && h) {
			var a = new Date;
			a.setDate(d);
			a.setHours(h, 0, 0, 0);
			var from = Math.floor(a.getTime() / 1000);
		} else {
			var from = options.getValue("TVTID.onfly.from");
		}
		var url = "http://tvtid.tv2.dk/js/fetch.js.php/from-" + from + ".js";
		var cache = getCachedVersion(url);
		if (cache != false) {
			if (!cb) {
				g_Feed = eval("(" + cache + ")");
			} else {
				cb(cache);
			}
			return cache;
		}
log("returning");
		if (connectivity_OK) {
			var res = xhrGet({
				url:url,
				onSuccess:typeof cb == "function" ? function (resText) {
					cb(resText);
					xml_ajaxIcon.visible = false;
				} : undefined
			});
			
			storeCachedVersion(url, res);
			if (!cb) {
				var x = eval("(" + res + ")");
				if(!def(x) || x.channels.length == 0) {
					alert('ERROR: ' + res);
					alert("evaluation => " + typeof x);
				}
				g_Feed = x;
				xml_ajaxIcon.visible = false;
			}
			httpRetries = 0;
			return res;
			return g_Feed
		}
	} catch (e) {
		e.message = "#getFeed:\n" + e.message;
		throw e;
	}
}

function hash(token) {}
function openCacheFolder() {
	if(vverbose)log(__FUNCTION())
	var cur = options.getValue("TVTID.cache.foldername");
alert('hier');
	var foo = new ActiveXObject("WScript.Shell");
	foo.run("file://" + (isWin ? "/" + cur.replace(/\\/g, "/") : cur));
}
function inst_step1() {
	opendetails("Installation 1 / 3", strings.INSTALLATION1,inst_step2);
}
function inst_step2() {

	var fso = framework.system.filesystem;
	var i = 0, folder, iter, username, base;
	if (isWin) {
		base = new ActiveXObject("Wscript.Shell").ExpandEnvironmentStrings("%APPDATA%");
		base = fso.GetFolder(base);
		base += "\\TVTID\\";
	} else if (isMac) {
		folder = fso.GetFolder("/Users/");
		iter = new Enumerator(folder.SubFolders);
		alert(iter.item());
		username = prompt(strings.INSTALLATION2, iter.item().GetBaseName());
		base = "/Users/" + username + "/.tvtid";
	} else {
		folder = fso.GetFolder("/home/");
		iter = new Enumerator(folder.SubFolders);
		for (; !iter.atEnd(); iter.moveNext()) {
			username = iter.item().Name;
			if(username.charAt(0) == "."
				|| username.indexOf('+') != -1) continue;
			else break;
		}
		username = prompt(strings.INSTALLATION2, iter.item().Name);
		base = "/home/" + username + "/.tvtid/";
	}
	try {
		if(fso.FolderExists(base))
			fso.CreateFolder(base);
	} catch(e) {
		log('FAILED' + __FUNCTION())
		options.remove("TVTID.cache.foldername");
	} finally {
		options.putValue("TVTID.cache.foldername", base);
	}
	setTimeout(function() {
		opendetails("Installation 2 / 3", strings.INSTALLATION3.replace(/CACHE_FOLDER/g, base), inst_step3);
	}, 500);
}
function inst_step3() {
	setTimeout(function() {
		opendetails("Installation 2 / 3", strings.INSTALLATION4, function() {
			options.putValue("TVTID.Install.wizard_has_run", "isset");
		});
	}, 500);
}
function inst_step4() {
	openCacheFolder();
	opendetails("Acceptér notifikation om favoritprogrammer",
		strings.INSTALLATION5.
		replace(/CACHE_FOLDER/, options.getValue("TVTID.cache.foldername")).
		replace(/SELECT_FILES/, (isWin ? "ggl-notifier.exe" : "ggl-notifier.*")).
		replace(/SELECT_INMENU/, (isMac ? "'Vis info'" : "'Egenskaber'")).
		replace(/SET_FORFILE/, (isWin ? "Eksekverbar" : (isLinux ? "Flag i feltet ud for 'Udførsel - Tillad kørtsel af filen'" : "intet (<i>fjern</i>) flag i 'Låst'")) )
		);
}
function inst_step_notify() {

	opendetails("Acceptér afvikling af notifikationr", strings.INSTALLATION6,  null, {
		accept: function accept_notify() {
			options.putValue("TVTID.Notify.notifications_ok", "yes");
			plugin.closeDetailsView();
			notify.start();
		},
		accept_dont_ask : function allways_notify() {
alert('hier');
			options.putValue("TVTID.Notify.dont_ask", "isset");
			options.putValue("TVTID.Notify.notifications_ok", "yes");
			plugin.closeDetailsView();
			notify.start();
		},
		reject : function never_notify() {
			options.putValue("TVTID.Notify.dont_ask", "isset");
			options.putValue("TVTID.Notify.notifications_ok", "no");
			plugin.closeDetailsView();
		},
		accept_dbus : function test_capeability () {
			var dbusCapeable = true; //framework.runtime.osName.toLowerCase().match("linux");
				var item = new ContentItem();
				item.heading = "Notification Example";
				item.snippet = strings.INSTALLATION7;
				plugin.AddContentItem(item, gddItemDisplayAsNotification);
				setTimeout(function() {
					var ok = confirm("Notification visible?")
					if(ok) {
						options.putValue("TVTID.Notify.uses_dbus", "isset");
						options.putValue("TVTID.Notify.dont_ask", "isset");
						plugin.closeDetailsView();
					}
				}, 750);
		}
	});
}
function clearAllSettings() {

	if(confirm("Sure to wipe settings??")) {
		options.remove("TVTID.cache.foldername");
		options.remove("TVTID.Channel.Favourites");
		options.remove("TVTID.Channel.HideCompleted");
		options.remove("TVTID.Channel.TotalPrPage");
		options.remove("TVTID.Channel.TotalTitles");
		options.remove("TVTID.Channel.VisibleTitles");
		options.remove("TVTID.Install.wizard_has_run");
		options.remove("TVTID.Monitor.Channels");
		options.remove("TVTID.Monitor.Interval");
		options.remove("TVTID.Monitor.Programs");
		options.remove("TVTID.Notify.dont_ask");
		options.remove("TVTID.Notify.notifications_ok");
		options.remove("TVTID.Notify.uses_dbus");
		options.remove("TVTID.onfly.from");
		options.remove("TVTID.onfly.Openstate");
		options.remove("TVTID.Sound.Active");
		options.remove("TVTID.Sound.Filename");
	}
}
function assertCacheDir() {
	log(__FUNCTION())
	if(!options.exists("TVTID.cache.foldername") || !options.exists("TVTID.Install.wizard_has_run")) {
		inst_step1();
	}
	return;
/*
	var res = prompt("", cur.length > 0 ? cur : base);
	if (res == false) {
		return;
	}
	var exists = fso.FolderExists(res);
	if (exists == true) {
		alert(res + " er nu valgt");
		options.putValue("TVTID.cache.foldername", res);
	} else {
		if (isWin && res.indexOf(":") != 1 || !isWin && res.indexOf("/") != 0) {
			alert("Angiv venligst " + (isWin ? "drev" : "/") + " som det f\xC3\xB8rste");
		} else if (confirm("Stien du har valgt existerer ikke, vil du oprette folderen?")) {
			var dirs, okpath, i;
			if (isWin) {
				dirs = res.split("\\");
				okpath = "";
				for (i = 1; i < dirs.length; i++) {
					if (i == 0) {
						okpath = dirs[i] + "\\";
					} else {
						if (!fso.FolderExists(okpath + dirs[i])) {
							if (!fso.CreateFolder(okpath + dirs[i])) {
								break;
							}
						}
						okpath += dirs[i] + "\\";
					}
				}
				okpath += "\\";
			} else {
				dirs = res.substring(1).split("/");
				okpath = "/";
				for (i = 0; i < dirs.length; i++) {
					if (dirs[i].length == 0) {
						continue;
					}
					if (!fso.FolderExists(okpath + dirs[i])) {
						if (!fso.CreateFolder(okpath + dirs[i])) {
							break;
						}
					}
					okpath += dirs[i] + "/";
				}
			}
			if (!okpath.match(res)) {
				alert("Fejlede, check for rettigheder");
			} else {
				options.putValue("TVTID.cache.foldername", okpath);
			}
		}
	}

	 */
}
function cleanCacheDir() {
	if (vverbose) {
		log(__FUNCTION());
	}
	var file, f, fc, s;
	var stale = ((new Date).getTime() - 86400) / 1000;
	var identifier = options.getValue("TVTID.cache.foldername");
	if (identifier == "") {
		return;
	}
	var fso = framework.system.filesystem;
	f = fso.GetFolder(identifier);
	fc = new Enumerator(f.files);
	for (; !fc.atEnd(); fc.moveNext()) {
		file = fc.item();
		if (file.name.match(/[0-9]*\.js/)) {
			if (parseInt(file.name.replace(/\.js/, "")) < stale) {
				file.Delete();
			}
		}
	}
}

function getCachedVersion(url) {
	if (true || vverbose) {
		log(__FUNCTION());
	}
	if(!options.exists("TVTID.cache.foldername")) return false
	log("get cache: " + url);
	var identifier = options.getValue("TVTID.cache.foldername");
	if (identifier == "") {
		return false;
	}
	if (url.match("fetch.js")) {
		identifier += url.substring(url.lastIndexOf("-") + 1);
	} else {
		for (var i = 0, sum = 0; i < url.length; i++) {
			sum += url.charCodeAt(i);
			if (i % 5 == 0) {
				identifier += sum + "";
				sum = 0;
			}
		}
	}
log("file: " + identifier);
	try {
		return file_get_contents(identifier, false);
	} catch (e) {
		gadget.debug.error(e.message);
		return false;
	}
}

function storeCachedVersion(url, contents) {
	if (vverbose) {
		log(__FUNCTION());
	}
	var identifier = options.getValue("TVTID.cache.foldername");
	if (identifier == "") {
		return false;
	}
	if(! /\/$/.test(identifier)) identifier += "/";
	if (url.match("fetch.js")) {
		identifier += url.substring(url.lastIndexOf("-") + 1);
	} else {
		for (var i = 0, sum = 0; i < url.length; i++) {
			sum += url.charCodeAt(i);
			if (i % 5 == 0) {
				identifier += sum + "";
				sum = 0;
			}
		}
	}
	log("put " + identifier);
	try {
		file_put_contents(identifier, contents);
	} catch (e) {
		gadget.debug.error(e);
	}
}

function file_put_contents(path, contents) {
	try {
		var fso = framework.system.filesystem;
		var lines = contents.split("\n");
		var file = fso.CreateTextFile(path);
		for (var i = 0; i < lines.length; i++) {
			file.WriteLine(lines[i]);
		}
		return true;
	} catch (e) {
		return false;
	}
}

function file_get_contents(path, isResource) {
	if (isResource) {
		return gadget.storage.openText(path);
	} else {
		if (framework.system.filesystem.FileExists(path)) {
			var fp = framework.system.filesystem.OpenTextFile(path);
			var content = fp.ReadAll();
			fp.Close();
			return content;
		}
	}
	return false;
}

function $Qr(qS, set) {
	var tagname, classname, id;
	var buf_set, results_set = [], parent;
	set.forEach(function (set_iter) {
		try {
			parent = set_iter;
			buf_set = [];
			if (qS.indexOf(".") != -1) {
				if (qS.charAt(0) != ".") {
					buf_set = qS.split(".");
					tagname = buf_set[0];
					classname = buf_set[1];
					buf_set = parent.getElementsByTagName(tagname);
					buf_set.forEach(function (iter) {
						if (hasClass(iter, classname)) {
							results_set.push(iter);
						}
					});
				} else {
					classname = qS.substring(1);
					buf_set = parent.getElementsByTagName("*");
					buf_set.forEach(function (iter) {
						if (hasClass(iter, classname)) {
							results_set.push(iter);
						}
					});
				}
			} else if (qS.indexOf("#") != -1) {
				if (qS.charAt(0) != "#") {
					buf_set = qS.split("#");
					tagname = buf_set[0];
					id = buf_set[1];
					buf_set = parent.getElementsByTagName(tagname);
					buf_set.forEach(function (iter) {
						if (iter.id == id) {
							results_set.push(iter);
						}
					});
				} else {
					id = qS.substring(1);
					buf_set = parent.getElementsByTagName("*");
					buf_set.forEach(function (iter) {
						if (iter.id == id) {
							results_set.push(iter);
						}
					});
				}
			} else {
				results_set = parent.getElementsByTagName(qS);
			}
		} catch (e) {
			log(e.message);
		}
	});
	return results_set;
}

function $Q(qStr, parent) {
	try {
		var results_set = [];
		var qA = qStr.split(" ");
		var qS;
		parent = parent || document.getElementsByTagName("body")[0];
		while (qA.length > 0) {
			qS = qA.shift();
			results_set = $Qr(qS, parent == null ? results_set : [parent]);
			if (results_set.length == 0) {
				return [];
			}
		}
		return results_set;
	} catch (e) {
		log(e.message);
	}
}

function def(obj) {
	return typeof obj != "undefined" && obj != null;
}

function getX(el) {
	if (typeof el.offsetX == "undefined") {
		return 0;
	}
	if (typeof el.offsetX == "string") {
		if (def(el.parentElement) && def(el.parentElement.width)) {
			return el.parentElement.width / 100 * parseInt(el.offsetX);
		} else {
			return 0;
		}
	} else {
		return el.offsetX;
	}
}

function getY(el) {
	if (typeof el.offsetY == "undefined") {
		return 0;
	}
	if (typeof el.offsetY == "string") {
		if (def(el.parentElement) && def(el.parentElement.height)) {
			return el.parentElement.width / 100 * parseInt(el.offsetY);
		} else {
			return 0;
		}
	} else {
		return el.offsetY;
	}
}

function findPos(el) {
	if (vvverbose) {
		log(__FUNCTION());
	}
	var x, y, buf;
	x = y = 0;
	if (el.parentElement) {
		buf = getX(el);
		if (def(buf)) {
			x = buf;
		}
		buf = getY(el);
		if (def(buf)) {
			y = buf;
		}while ((el = el.parentElement)) {
			buf = getX(el);
			if (def(buf)) {
				x += buf;
			}
			buf = getY(el);
			if (def(buf)) {
				y += buf;
			}
		}
	}
	if (vvverbose) {
		log("<-- " + x + "x" + y);
	}
	return {
		x:x,
		y:y
	};

}
var prefs = {
	channels:{
		maxProgramsOnRender:options.exists("TVTID.Channel.VisibleTitles") ? options.getValue("TVTID.Channel.VisibleTitles") : 2,
		maxProgramsInTotal:options.exists("TVTID.Channel.TotalTitles") ? options.getValue("TVTID.Channel.TotalTitles") : 4,
		maxPrPage: options.exists("TVTID.Channel.TotalPrPage") ? options.getValue("TVTID.Channel.TotalPrPage") : 4,
		favourites:options.exists("TVTID.Channel.Favourites") ? options.getValue("TVTID.Channel.Favourites") : ""
	},
	monitor:{
		programs:options.getValue("TVTID.Monitor.Programs"),
		channels:options.getValue("TVTID.Monitor.Channels")
	},
	myChannels:[],
	hidePreviousPrograms:!!options.getValue("TVTID.Channel.HideCompleted")
};
function isSubscribed(name, id) {
	if (prefs.channels.favourites.length != 0) {
		for (var i = 0; i < prefs.myChannels.length; i++) {
			if (trueChanId(name) == prefs.myChannels[i]) {
				return true;
			}
		}
		return false;
	} else {
		for (var i = 0; i < g_Feed.def_channel_ids.length; i++) {
			if (g_Feed.def_channel_ids[i] == id) {
				return true;
			}
		}
		return false;
	}
}

function trueChanId(chan) {
	var s = chan.replace(/_/g, " ").replace(/\$D/g, "/").replace(/\$EX/g, "!").replace(/\$K/g, ".").replace(/\$P/g, "+").replace(/\$M/g, "-").replace(/\$S/g, "#").replace(/\$A/g, "&").replace(/\$Q/g, "'");
	return s;
}

function mangleChanId(chan) {
	var s = chan.replace(/\ /g, "_").replace(/\!/g, "$EX").replace(/\//g, "$D").replace(/\./g, "$K").replace(/\+/g, "$P").replace(/\-/g, "$M").replace(/#/g, "$S").replace(/&/g, "$A").replace(/(\`|\')/g, "$Q");
	return s;
}

function mangleEntities(str) {
	var s = str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
	s = s.replace(/\"/g, '&quot;').replace(/\'/g, "&quot;");
	return s;
}

function quoteRegExp(testExp) {
	return testExp.replace(/\+/g, "\\+").replace(/\-/g, "\\-").replace(/\$/g, "\\$").replace(/\^/g, "\\^").replace(/\[/g, "\\[").replace(/\]/g, "\\]").replace(/\}/g, "\\{").replace(/\}/g, "\\}").replace(/\ /g, "\\ ");
}

function getIndex(mangledChanId, notMangled) {
	if (vverbose) {
		log(__FUNCTION());
	}
	var trueId = !!notMangled ? mangledChanId : trueChanId(mangledChanId);
	var exp = RegExp("^" + quoteRegExp(trueId) + "$");
	for (var index = 0; index < g_Feed.channels.length; index++) {
		if (exp.test(g_Feed.channels[index].name)) {
			if (vverbose) {
				log("-->" + index);
			}
			return index;
		}
	}
	return -1;
}
